package com.example.flutter_native_message_app;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

import java.util.HashMap;
import java.util.Map;

//代码清单9-2
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMessageCodec;

public class MainActivity extends FlutterActivity {

    //上下文对象
    private Context mContext;

    //消息通道
    private MethodChannel mMethodChannel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        //注册监听
        registerChannelFunction();

        registerMessageChannelFunction();

        registerEventChannerl();

        TestViewFactory.registerWith(getFlutterEngine());
    }

    //代码清单9-2-1 注册监听
    //记着要在 onCreat方法中调用
    private void registerChannelFunction() {
        //Flutter运行环境参数封装类
        FlutterEngine lFlutterEngine = getFlutterEngine();
        if (lFlutterEngine == null) {
            Log.e("ERROR", "注册消息通道失败 FlutterEngine = null");
            return;
        }
        //获取Dart缓存编译对象
        DartExecutor lDartExecutor = lFlutterEngine.getDartExecutor();
        //获取默认的 BinaryMessenger
        BinaryMessenger lBinaryMessenger = lDartExecutor.getBinaryMessenger();
        //消息通道名称
        String channelName = "flutter_and_native_101";
        //构建消息通道
        mMethodChannel = new MethodChannel(lBinaryMessenger, channelName);
        //设置监听 这里使用的是匿名内部类的方式
        mMethodChannel.setMethodCallHandler(methodCallHandler);
    }

    //代码清单9-2-2 监听回调
    MethodChannel.MethodCallHandler methodCallHandler = (call, result) -> {
        //获取方法名称
        String lMethod = call.method;
        //获取参数
        Object lArguments = call.arguments;
        Map<String, Object> arguments = null;
        if (lArguments != null) {
            arguments = (Map<String, Object>) lArguments;
            //获取到Flutter传递的参数
        }
        //处理消息
        if (lMethod.equals("test")) {
            Toast.makeText(mContext,
                    "flutter 调用到了 android test",
                    Toast.LENGTH_SHORT).show();
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("message", "ABC");
            resultMap.put("code", 200);
            //发消息至 Flutter
            //此方法只能使用一次
            result.success(resultMap);

            //代码块9-2-3
            Map<String, Object> resultMap2 = new HashMap<>();
            resultMap2.put("message", "android 主动调用 flutter test 方法");
            resultMap2.put("code", 200);
            mMethodChannel.invokeMethod("test2", resultMap2);


        } else {
            result.notImplemented();
        }
    };


    /**
     * 代码清单9-1-7
     * 处理 Flutter 发送过来的消息
     *
     * @param result    回调 Flutter 的对象
     * @param method    Flutter 传递的方法名称
     * @param arguments Flutter 传递的参数
     */
    private void methodCallFunction(MethodChannel.Result result,
                                    String method,
                                    Map<String, Object> arguments) {
        if (method.equals("test")) {
            Toast.makeText(mContext,
                    "flutter 调用到了 android test",
                    Toast.LENGTH_SHORT).show();
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("message", "ABC");
            resultMap.put("code", 200);
            //发消息至 Flutter
            //此方法只能使用一次
            result.success(resultMap);

        } else {
            result.notImplemented();
        }
    }

    //--------------------------------------------------------------------------------------------------------------
    //代码清单9-5-1 注册监听
    ///BasicMessageChannel实例对象
    private BasicMessageChannel<Object> mMessageChannel;

    ///这个方法需要在 onCreate 方法中调用
    private void registerMessageChannelFunction() {

        ///获取 BinaryMessenger
        BinaryMessenger lBinaryMessenger = getFlutterEngine()
                .getDartExecutor()
                .getBinaryMessenger();
        //消息接收监听
        //BasicMessageChannel （主要是传递字符串和一些半结构体的数据）
        mMessageChannel = new BasicMessageChannel<Object>(
                lBinaryMessenger,
                "flutter_and_native_100",
                StandardMessageCodec.INSTANCE);

        // 接收消息监听
        // 监听参数 handlerArgument 就是 Flutter中传过来的消息
        // 参数 reply就是BasicMessageChannel.Reply<Object> 类型
        mMessageChannel.setMessageHandler((handlerArgument, reply) -> {
            ///获取传递的参数
            Map<String, Object> arguments = (Map<String, Object>) handlerArgument;
            ///消息处理
            try {
                baseMessageChannelCallFunction(reply, arguments);
            } catch (Exception e) {
                e.printStackTrace();
                ///异常回调
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("message", "操作异常 " + e.getMessage());
                resultMap.put("code", 500);
                //回调 此方法只能使用一次
                reply.reply(resultMap);
            }
        });

    }

    //代码清单9-5-2 处理参数
    private void baseMessageChannelCallFunction(
            BasicMessageChannel.Reply<Object> reply,
            Map<String, Object> arguments) {
        if (arguments.containsKey("method")) {
            //处理参数
            //方法名标识
            String lMethod = (String) arguments.get("method");
            //测试 reply.reply()方法 发消息给Flutter
            if (lMethod.equals("test")) {
                Toast.makeText(mContext, "调用到了test",
                        Toast.LENGTH_SHORT).show();
                //回调Flutter
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("message", "reply.reply 返回给flutter的数据");
                resultMap.put("code", 200);
                //回调 此方法只能使用一次
                reply.reply(resultMap);
                return;
            }
        }
        reply.reply("没有实现方法");
    }

    //代码清单9-5-3
    ///Android中 BasicMessageChannel 向Flutter中主动发送消息
    private void messageChannelSendFunction() {
        ///代码清单9-1-21
        //构建参数
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("message", "ABCSD");
        resultMap.put("code", 200);

        //向 Flutter 中发送消息
        //参数 二可以再次接收到 Flutter 中的回调
        //也可以直接使用 mMessageChannel.send(resultMap）
        mMessageChannel.send(resultMap, new BasicMessageChannel.Reply<Object>() {
            @Override
            public void reply(Object o) {
                ///再次接收到的回执消息
                Log.d("mMessageChannel", "mMessageChannel send 回调 " + o);
            }
        });
    }

    //--------------------------------------------------------------------------------------------------------------
    ///代码清单9-8 EventChannel 通信
    private EventChannel.EventSink mEventSink;

    ///需要在 MainActivity的OnCreate方法中调用
    private void registerEventChannerl() {

        ///获取当前默认的 BinaryMessenger
        BinaryMessenger lBinaryMessenger = getFlutterEngine()
                .getDartExecutor()
                .getBinaryMessenger();
        //消息通道名称
        String channelName = "flutter_and_native_103";
        //创建 EventChannel 通道
        EventChannel lEventChannel = new EventChannel(lBinaryMessenger, channelName);
        //设置 StreamHandler
        lEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
            // onListen 回调则代表通道已经建好，可以发送数据了
            @Override
            public void onListen(Object o, EventChannel.EventSink eventSink) {
                //注意是通过 EventSink 发送消息
                mEventSink = eventSink;

            }

            /// onCancel 表示 Flutter 端已取消接收消息
            @Override
            public void onCancel(Object o) {
                mEventSink = null;

            }
        });
    }
    ///代码清单9-8-1
    private final Handler mHandler = new Handler();
    //使用 EventChannel 通道向 Flutter发送消息
    //这里发送的消息为 String 类型
    //可以根据实际项目开发中发送 其他数据类型
    private void eventSendMessageFunction(String messsage) {
        if (mEventSink != null) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mEventSink.success(messsage);
                }
            });

        } else {
            Log.e("ERROR", "EventSink is null");
        }
    }


}
